﻿using System;
using System.Collections.Generic;
using System.Linq;
using LinqSpecs;
using NHibernate;
using NHibernate.Linq;
using PCE.Domain;

namespace PCE.Data.NH
{
	public class NHibernateRepository<TEntity, TKey> : IRepository<TEntity, TKey>
		where TEntity : Entity<TKey>
		where TKey : IEquatable<TKey>
	{
		private readonly ISessionFactory _sessionFactory;

		protected ISession Session
		{
			get { return _sessionFactory.GetCurrentSession(); }
		}

		public NHibernateRepository(ISessionFactory sessionFactory)
		{
			_sessionFactory = sessionFactory;
		}

		public TEntity Get(TKey key)
		{
			return Session.Get<TEntity>(key);
		}

		public void Save(TEntity entity)
		{
			Session.SaveOrUpdate(entity);
		}

		public int Count(Specification<TEntity> spec)
		{
			return Session.Query<TEntity>().Count(spec.IsSatisfiedBy());
		}

		public TEntity Find(Specification<TEntity> spec)
		{
			return GetQuery(spec).SingleOrDefault();
		}

		public IEnumerable<TEntity> FindAll(Specification<TEntity> spec)
		{
			return GetQuery(spec).ToList();
		}

		private IQueryable<TEntity> GetQuery(Specification<TEntity> spec)
		{
			return Session.Query<TEntity>().Where(spec.IsSatisfiedBy());
		}
	}
}